package aep

import (
	"encoding/json"
	"errors"
	aepapi2 "gitee.com/injoyai/goutil/iot/aep/sdk/aep/apis/Aep_device_command"
	"gitee.com/injoyai/goutil/iot/aep/sdk/aep/apis/Aep_device_management"
	"gitee.com/injoyai/goutil/string/logs/v1"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
)

type Aep struct {
	APIkey    string
	AppID     string
	AppSecret string
	ProductID int

	debug   bool //调试模式
	AepFunc      //处理数据
}

type AepFunc struct {
	FnData  func(*DataBack) error  //处理上报数据
	FnLine  func(*LineBack) error  //处理在线离线
	FnEvent func(*EventBack) error //处理事件上报
	FnOrder func(*OrderBack) error //处理命令回调
	FnTup   func(*TupBack) error   //处理Tup 数据
}

// Func 设置数据处理方法
func (this *Aep) Func(fn AepFunc) *Aep {
	this.AepFunc = fn
	return this
}

func (this *Aep) Debug(b ...bool) *Aep {
	this.debug = !(len(b) > 0 && !b[0])
	return this
}

func (this *Aep) Handler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(200)
	req := new(ResBack)
	bodyBs, err := ioutil.ReadAll(r.Body)
	if err != nil {
		logs.Err(err)
		w.WriteHeader(500)
		return
	}

	if this.debug {
		print("接收", string(bodyBs))
	}
	logs.PrintErr(json.Unmarshal(bodyBs, req))
	var data IBack = new(ResBack)
	switch req.MsgType {
	case MsgData:
		data = new(DataBack)
	case MsgOrder:
		data = new(OrderBack)
	case MsgEvent:
		data = new(EventBack)
	case MsgLine:
		data = new(LineBack)
	case MsgTup:
		data = new(TupBack)
	}
	logs.PrintErr(json.Unmarshal(bodyBs, data))
	err = data.Deal(this)
	if err != nil {
		logs.Err(err)
		w.WriteHeader(500)
	}
}

// Create 注册设备
func (this *Aep) Create(imei, name string) (string, error) {
	body := &RegisterDeviceReq{
		ProductID:  this.ProductID,
		Imei:       imei,
		DeviceName: name,
		Operator:   "设备注册",
	}
	data, err := aepapi.CreateDevice(this.AppID, this.AppSecret, this.APIkey, body.toString())
	if err != nil {
		return "", err
	}
	bs, err := ioutil.ReadAll(data.Body)
	if err != nil {
		return "", err
	}
	type res struct {
		Res
		Result struct {
			DeviceID string `json:"deviceId"`
		} `json:"result"`
	}
	l := new(res)
	if err := json.Unmarshal(bs, l); err != nil {
		return "", err
	}
	return l.Result.DeviceID, this.dealErr(l.Err())
}

// Delete 删除设备
// @deviceIds,平台id
func (this *Aep) Delete(deviceIds ...string) error {
	did := strings.Join(deviceIds, ",")
	data, err := aepapi.DeleteDevice(this.AppID, this.AppSecret, this.APIkey, strconv.Itoa(this.ProductID), did)
	if err != nil {
		return err
	}
	bs, err := ioutil.ReadAll(data.Body)
	if err != nil {
		return err
	}
	if strings.Contains(string(bs), "此设备不存在") {
		return nil
	}
	res := new(Res)
	if err := json.Unmarshal(bs, res); err != nil {
		return err
	}
	return this.dealErr(res.Err())
}

/*
Send
Content: struct {
			DataType int    `json:"dataType"` //数据类型：1字符串，2十六进制
			Payload  string `json:"payload"`  //指令内容,数据格式为十六进制时需要填十六进制字符串,
		}{
			DataType: 2,
			Payload:  order,
		},

*/
//设备通讯
//@deviceId,平台id
//@下发内容
func (this *Aep) Send(deviceId string, content interface{}) (string, error) {
	body := &SendDeviceReq{
		Content:   content,
		DeviceID:  deviceId,
		Operator:  "api",
		ProductID: strconv.Itoa(this.ProductID),
		Level:     1,
	}
	if this.debug {
		print("发送", body.toString())
	}
	data, err := aepapi2.CreateCommand(this.AppID, this.AppSecret, this.APIkey, body.toString())
	if err != nil {
		return "", err
	}
	bs, err := ioutil.ReadAll(data.Body)
	if err != nil {
		return "", err
	}
	res := new(Res)
	if err := json.Unmarshal(bs, res); err != nil {
		return "", err
	}
	return res.GetTaskID(), this.dealErr(res.Err())
}

//加工处理错误
func (this *Aep) dealErr(err error) error {
	if err != nil {
		switch err.Error() {
		case "指令下发，设备状态不合法":
			err = errors.New("设备未激活,需要重启")
		case "IMEI号已存在":
			err = errors.New("设备在AEP平台已存在")
		}
	}
	return err
}
